<?php
/**此类用于检测WBS的前置任务，算法有朱老师和张敏设计和编写，由吴国文整合到系统中
 * March 16 2005
 */
class PreTaskCheck {
	var $checkResult = "";	//用来保存检测结果
	
	//类构造函数
	function PreTaskCheck() {}
	
	/**此函数功能是判断工序多余情况，利用array_intersect()返回工序的紧前工序与紧前工序的紧前工序的集合
	 *如工序4的紧前工序为1、3，而3的紧前工序为1，则取交集为1且非0，故1在4中是多余的工序
	 */
	function checkOtiose($k,$s,$m) {
		
		$t=array_intersect($k,$s);//找到k与s数组的交集，然后判断是否为空，若非空，则表明有多余情况
		if (count($t)!=0) { 
			//echo "在".$m."号工序中存在多余情况！";
			$this->checkResult = "如果添加此前置任务，那么";
			foreach($t as $key=>$value) {
				//echo  $value."号工序应删除！ ";
				$this->checkResult .= $value."#,";
			} 
			$this->checkResult .= "前置任务将会是多余的，请先更改！";
			return $key;
		} else {
			return 0;
		}
	}

	/**fun1函数功能为：利用函数递归找出工序中的循环回路并给以提示。固定工序j,然后将其当前紧前工序记为o(old),
	 *然后找出o的每一元素的紧前工序b[o(j)]，并将o与b[o(j)]合并记为new,将new与$a及$o求差集判空，
	 *若为空表明前序工序集查找结束，否则，继续查找，如此递归。若工序j在其紧前工序集合中，说明j与其它工序形成循环回路
	 */
	function checkLoopPath($j,$o,$d,$a) {   
		global $n;

		$n=array();
		$new=$o;
		foreach($o as $key=>$value)
		{    
			$k=$value;
			if(in_array(0,$d[$k]))
		  		$key+1;
			else
			{ 
				$new=array_merge($new,$d[$k]);
				$new=array_unique($new);
				$key+1;
			} 
		}
		
		$e=array_diff($new,$o);
		$f=array_diff($a,$new);
	
		if($e==null || $f==null)
		{    
			$n=array($j=>$new);
			if (in_array($j,$n[$j]))
				//echo $j."#与其它工序组成循环回路，请检查!<br>";
				$this->checkResult .= $j."#,";
		} else
			$this->checkLoopPath($j,$new,$d,$a);  
	}

	/**调用此函数开始检测，前面两个函数都是为此函数服务
	 */
	function startCheck($a,$b) {
		$l=0;//此变量记录删除数组中元素的个数

		/*******此段开始判定不衔接情况**********/
		for ($i=1;$i<=count($b);$i++)  
		{
			$c=array_diff($b[$i],$a);
			foreach ($c as $key=>$value)
			{
				if($value!=0) {
					//echo $value."号工序不存在! ";
					$this->checkResult = $value."#任务不存在!";
					$d=$value;
					unset($b[$i][$key]);
					$l++;
				}
			}
		} 
		/*******完成**********/

		/*********此段为判定工序多余情况，调用checkOtiose函数***********/
        //如果前面检测没问题，则继续下一步检测
		if (is_null($this->checkResult) || $this->checkResult=="") { 
		for($i=1;$i<=count($b);$i++)   
		{ 
			for($j=1;$j<=count($b[$i])+$l;$j++)
			{
				if(isset($b[$i][$j])) {
					$c=$b[$i][$j]; //将第i工序的紧前工序一一找其紧前工序，即将b[k][s]先赋给c
					if($c==$i)
					{  
						//echo $i."工序自身冗余! ";
						$this->checkResult = $i."#任务自身冗余!";
						unset($b[$i][$j]);
						$l++;
					} else {
						if($c!=0)//因为0不需要比较
						{
							$d=$b[$i];//把i的紧前工序赋给d数组
							$x=$b[$c];//然后将c的紧前工序复制给x数组,使x与i的紧前工序比较，用递归函数
							$r=$this->checkOtiose($d,$x,$i);
							if($r!=0)
							{
								$ry=$b[$i][$r];//将冗余的工序赋给ry,以用来判断此工序是否还在原工序的紧前工序集合中
								unset($b[$i][$r]);//将多余的紧前工序销毁 
 							}
						}	
					} 
				}
			}
		} } //结束For循环和If语句
		/*******完成**********/
		
		/************开始工序循环回路检查**************/
        //如果前面检测没问题，则继续下一步检测
		if (is_null($this->checkResult) || $this->checkResult=="") { 
			for($i=1;$i<=count($b);)
			{ 
				if(is_null($b[$i]) || in_array(0,$b[$i])) {
					$i++;
				} else {
					$this->checkLoopPath($i,$b[$i],$b,$a); 
					$i++; 
				}
			} //结束For循环
			if (!is_null($this->checkResult) && $this->checkResult != "") {
				$this->checkResult = "如果添加此前置任务，则".$this->checkResult;
                $this->checkResult = $this->checkResult."组成循环回路，所以不能添加！";
            }
		}//结束If语句
		/*******完成**********/
		
		return $this->checkResult; //返回检测结果
	}//结束startCheck()函数
} //结束类

require_once("../../config/config.inc.php");

$sProjectID   = $_SESSION["task_project_id"];
$sTaskEditAll = fn_isNull($_SESSION["task_enable_editall"],"none"); //editall

if ($sTaskEditAll != "editall") {
    echo "{success:false,msg:'no rights'}";
    return;
}

/****/
    $sTaskID      = fn_getParam('strTaskID','');
    $sPreTaskID   = fn_getParam('strPreTaskID','');
    $sPreTaskType = fn_getParam('strPreTaskType','');
    $sStayTime    = fn_getParam('strStayTime','0');
    $sPreRemark   = fn_getParam('strPreRemark','');
/****
    $sTaskID      = "16";
    $sPreTaskID   = "12";
    $sPreTaskType = "FS";
    $sStayTime    = "1";
    $sPreRemark   = "ddd";
****/
    //先校验此前置任务是否已经添加
    $sql = "SELECT COUNT(1) FROM $TABLE_PRETASK ";
    $sql.= "WHERE TASKID='".$sTaskID."' AND PRETASKID='".$sPreTaskID."'";
    if ($DB->getFirstField($sql) > 0) {
        echo "{success:false,msg:'该前置任务已经存在，不能重复添加'}";
        return;
    }

    //否则开始校验是否能添加此前置任务
    //获取该项目前置任务列表
    $aPretask = array(array());
    $sql  = "SELECT A.TASKID, B.ORDERNUMB FROM $TABLE_PRETASK A,$TABLE_TASK B ";
    $sql .= "WHERE B.PROJECTID='$sProjectID' AND A.PRETASKID=B.ID ";
    $sql .= "ORDER BY A.TASKID,B.ORDERNUMB";
    $result = $DB->query($sql);
    $iIndex = 0;
    while ($rs = $DB->fetchArray($result)) {
        $aPretask[$iIndex][0] = $rs["TASKID"];
        $aPretask[$iIndex][1] = $rs["ORDERNUMB"];
        $iIndex++;
    }
    //将要添加的前置任务也列出来一起检测
    $aPretask[$iIndex][0] = $sTaskID; //当前任务的ID
    //$aPretask[$iIndex][1] = $iOrderNumb;//要添加的前置任务（不是sTaskID）的Ordernumb
    $DB->freeResult($result);
    //print_r($aPretask);echo "<br>";

    //获取所选择项目的工作分解结构列表
    $sql = "SELECT ID,ORDERNUMB FROM $TABLE_TASK WHERE PROJECTID='$sProjectID' ORDER BY ORDERNUMB";
    $result = $DB->query($sql);
    $aIndex = 1;
    $aTask  = array();
    $bTask  = array();
    while ($row = $DB->fetchArray($result)) {
        $aTask[$aIndex] = $row["ORDERNUMB"];
        //接上面的更改
        if ($sPreTaskID == $row["ID"]) {
            $aPretask[$iIndex][1] = $row["ORDERNUMB"];
        }
        //从$aPretask数组中获取前置任务，并构造新的数组
        $bTask[$aIndex] = array();
        $k = 1;
        for ($i=0; $i<count($aPretask)&&count($aPretask[0])>0; $i++) {
            if ($aPretask[$i][0] == $row["ID"]) {
                $bTask[$aIndex][$k] = $aPretask[$i][1];
                $k++;
            }
        }
        $aIndex++;
    }
    $DB->freeResult($result);
    //初始化类，调用检测函数，检测完就摧毁数组变量
    $cCheck = new PreTaskCheck();
    $sResult= $cCheck->startCheck($aTask,$bTask);
    //print_r($aTask);echo "<br>";print_r($bTask);
    unset($aTask);
    unset($bTask);
    unset($aPretask);
    //$sResult = print_r($aPretask,true);
    //print_r($aPretask);

    if (is_null($sResult) || $sResult=="") {
        $sql = "INSERT INTO $TABLE_PRETASK(TASKID,PRETASKID,PRETASKTYPE,STAYTIME,REMARK) ";
        $sql.= "VALUES('".$sTaskID."','".$sPreTaskID."','".$sPreTaskType."',".$sStayTime.",'".$sPreRemark."')";
        $DB->query($sql);
        $sResult = "前置任务添加成功";

        echo "{success:true,msg:'".$sResult."'}";
    } else {
        echo "{success:false,msg:'".$sResult."'}";
    }

?>